package netmon.gui;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * Main GUI for the Network Monitor
 * @author Marc Backes
 * 
 */
public class NetmonMainJFrame extends JFrame {
	private static final long serialVersionUID = 1L;

	private NetmonGUIController guiC;

	/* GUI components */
	private JLabel lblHostAndIP = new JLabel("Host/IP: /");									// Displays Host/IP
	private JLabel lblOS = new JLabel("Operating system: /");								// Displays Operating system
	private JLabel lblResponsible = new JLabel("Responsible: /");							// Displays station's responsible
	private JLabel lblLocation = new JLabel("Location: /");									// Displays station's location
	private JLabel lblMacAddress = new JLabel("MAC address: /");							// Displays interface's MAC
	private JLabel lblUptime = new JLabel("Uptime: /");										// Displays system uptime
	private JLabel lblDroppedPackages = new JLabel("Dropped packages: /");					// Displays dropped packages
	private JLabel lblNOfConnections = new JLabel("Number of connections: /");				// Displays the number of connections
	private JLabel lblUpSpeed = new JLabel("Upspeed: /");									// Displays interface's upload speed
	private JLabel lblDownSpeed = new JLabel("Downspeed: /");								// Displays interface's download speed
	private JLabel lblnOfRunningProcesses = new JLabel("Number of running processes: /");	// Displays number of nurring processes

	private DefaultComboBoxModel hostsModel = new DefaultComboBoxModel();					// Contains all hosts (read from 'hosts.conf')
	private JComboBox cmbHosts = new JComboBox(hostsModel);									// Displays all the hosts from 'hostsModel'
	private DefaultComboBoxModel interfacesModel = new DefaultComboBoxModel();				// Contains all the interfaces of the host
	private JComboBox cmbInterfaces = new JComboBox(interfacesModel);						// Displays all interfaces from 'interfacesModel'
//	private JButton btnShowConnTable = new JButton("Show table");
	private JButton btnRefresh = new JButton("Refresh");									// Button to refresh all data
	
	private LoadBar upBar = new LoadBar();													// Bar showing the upload speed compared to maximum
	private LoadBar downBar = new LoadBar();												// Bar showing the download speed compared to maximum

	/* End GUI components */

	private int interfaceNumber;															// The interface which is currently selected
	private String hostName;																// The hostname which is currently selected

	/**
	 * Constructor: Initializes GUI Attention: It does NOT display the GUI. Use
	 * <i>coldStart()</i> or <i>warmStart()</i> for that!
	 */
	public NetmonMainJFrame(String version, NetmonGUIController guiC) {
		this.guiC = guiC;
		setTitle("NetMon " + version);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(500, 350);
		init();
		draw();
	}

	/**
	 * Generates the GUI: Set layout and add components
	 */
	public void draw() {
		JPanel pnlInterface = new JPanel();
		JPanel pnlUpspeed = new JPanel();
		JPanel pnlDownspeed = new JPanel();
		setLayout(new GridLayout(17, 1));
		add(cmbHosts);
		add(lblHostAndIP);
		add(lblOS);
		add(lblResponsible);
		add(lblLocation);
		add(lblnOfRunningProcesses);
		add(new JLabel());
		add(lblUptime);
		add(new JLabel());

		pnlInterface.setLayout(new GridLayout(1,2));
		pnlInterface.add(cmbInterfaces);
		pnlInterface.add(new JLabel());
		add(pnlInterface);
		add(lblMacAddress);
		add(lblDroppedPackages);		
		add(lblNOfConnections);
		
		
		pnlUpspeed.setLayout(new GridLayout(1,2));
		pnlUpspeed.add(lblUpSpeed);
		pnlUpspeed.add(upBar);
		add(pnlUpspeed);
		
		pnlDownspeed.setLayout(new GridLayout(1,2));
		pnlDownspeed.add(lblDownSpeed);
		pnlDownspeed.add(downBar);
		add(pnlDownspeed);	

		
		add(new JLabel());
		add(btnRefresh);
	}

	/**
	 * Initializes the graphical components (creating and adding listener)
	 */
	public void init(){
		/**
		 * ActionListener for the button <i>btnRefresh</i>
		 */
		ActionListener actionListener = new ActionListener() {
			/* This method is called when 'btnRefresh' has been pressed */
			public void actionPerformed(ActionEvent actionEvent) {
				guiC.refresh();
			}
		};

		/**
		 * ItemListener for the comboboxes <i>cbmHosts</i> and <i>cmbInterfaces</i>
		 */
		class ComboBoxChangedListener implements ItemListener {
			// This method is called only when a new item has been selected.
			public void itemStateChanged(ItemEvent evt) {
				if (evt.getStateChange() == ItemEvent.SELECTED) {
					/* Selected another interface */
					if(evt.getSource().equals(cmbInterfaces)){
						guiC.refreshTransferRates("Waiting...", "Waiting...");						// Update GUI
						interfaceNumber=cmbInterfaces.getSelectedIndex();							// Save
						guiC.changedInterface();
					/* Selected another host */
					} else if(evt.getSource().equals(cmbHosts)){						
						hostName = (String)cmbHosts.getItemAt(cmbHosts.getSelectedIndex());			// Save
						guiC.changeHost(hostName);
					}
				}
			}
		}
		
		/* Adding the listeners to the components */
		ComboBoxChangedListener interfaceListener = new ComboBoxChangedListener();
		ComboBoxChangedListener hostListener = new ComboBoxChangedListener();
		cmbInterfaces.addItemListener(interfaceListener);
		cmbHosts.addItemListener(hostListener);
		btnRefresh.addActionListener(actionListener);
	}

	
	/* =========================== Setters =========================== */

	/**
	 * Setting the hostname and IP address
	 * @param host Hostname
	 * @param ip IP address of the station
	 */
	public void setHostAndIP(String host, String ip) {
		this.lblHostAndIP.setText("Host: " + host + " (" + ip + ")");
	}

	/**
	 * Setting the operating system
	 * @param OS Operating system of the system
	 */
	public void setOS(String OS) {
		this.lblOS.setText("Operating system: " + OS);
	}

	/**
	 * Setting the station's responsible
	 * @param responsible Responsible of the station
	 */
	public void setResponsible(String responsible) {
		this.lblResponsible.setText("Responsible: " + responsible);
	}

	/**
	 * Setting the station's location
	 * @param location Location of the station
	 */
	public void setLocation(String location) {
		this.lblLocation.setText("Location: " + location);
	}

	/**
	 * Setting current uptime<br>
	 * This method is part part of the method <i>continouslyRefresh()</i> of the class <i>NetmonGUIController</i>
	 * @param uptime Uptime (xx hours, xx minutes, xx seconds)
	 */
	public void setUptime(String uptime) {
		this.lblUptime.setText("Uptime: " + uptime);
	}

	/**
	 * Setting the number of dropped packages<br>
	 * This method is part part of the method <i>continouslyRefresh()</i> of the class <i>NetmonGUIController</i>
	 * @param droppedPackages Number of dropped packages
	 */
	public void setDroppedPackages(String droppedPackages) {
		this.lblDroppedPackages.setText("Dropped packages (since uptime): " + droppedPackages);
	}

	/**
	 * Setting the number of current connections<br>
	 * This method is part part of the method <i>continouslyRefresh()</i> of the class <i>NetmonGUIController</i>
	 * @param nOfConnections
	 */
	public void setNOfConnections(String nOfConnections) {
		this.lblNOfConnections.setText("Number of connections: " + nOfConnections);
	}

	/**
	 * Setting the current upload speed of the selected interface<br>
	 * This method is part part of the method <i>continouslyRefresh()</i> of the class <i>NetmonGUIController</i>
	 * @param upSpeed Upload speed
	 */
	public void setUpSpeed(String upSpeed) {
		this.lblUpSpeed.setText("Upspeed: " + upSpeed);									// Update GUI
		try{
			upBar.setCurrent(new Double(upSpeed.substring(0,upSpeed.indexOf(' '))));	// Update loading bar
		} catch(Exception ex) {
			/* 
			 * Here occur only String manipulation errors.
			 * They will be ignored
			 */
		}
	}

	/**
	 * Setting the current download speed of the selected interface<br>
	 * This method is part part of the method <i>continouslyRefresh()</i> of the class <i>NetmonGUIController</i>
	 * @param downSpeed Download speed
	 */
	public void setDownSpeed(String downSpeed) {
		this.lblDownSpeed.setText("Downspeed: " + downSpeed);									// Update GUI
		try {
			downBar.setCurrent(new Double(downSpeed.substring(0,downSpeed.indexOf(' '))));		// Update loading bar
		} catch(Exception ex) {
			/* 
			 * Here occur only String manipulation errors.
			 * They will be ignored
			 */
		}
	}

	/**
	 * Setting the number of current running processes<br>
	 * This method is part part of the method <i>continouslyRefresh()</i> of the class <i>NetmonGUIController</i>
	 * @param nOfRunningProcesses Number of running processes
	 */
	public void setnOfRunningProcesses(String nOfRunningProcesses) {
		this.lblnOfRunningProcesses.setText("Number of running processes: " + nOfRunningProcesses);
	}

	/**
	 * Set the MAC address of the currently selected interface
	 * @param mac MAC address
	 */
	public void setMacAddress(String mac){
		this.lblMacAddress.setText("MAC address: "+ mac);
	}

	/* =========================== End Setters =========================== */
	
	/**
	 * Add an interface to the model <i>interfacesModel</i>
	 * @param interfaceName The interface name of the new interface
	 */
	public void addInterface(String interfaceName){
		interfacesModel.addElement(interfaceName);
	}

	/**
	 * Add an host to the model <i>hostsModel</i>
	 * @param hostName The host name of the new host
	 */
	public void addHost(String hostName){
		hostsModel.addElement(hostName);
	}

	/**
	 * Returns the index of the selected interface
	 * @return Index of the interface (beginning with 1)
	 */
	public int getInterfaceNumber(){
		return interfaceNumber+1;
	}

	/**
	 * Returns the name of the selected host
	 * @return Hostname of the station
	 */
	public String getHostName(){
		return hostName;
	}

	/**
	 * Cleans the model <i>hostsModel</i> and combobox <i>cbmHosts</i>
	 */
	public void cleanHosts(){
		cmbHosts.removeAllItems();				// Deletes all items from the model
		hostsModel.removeAllElements();			// Deletes all items from the combobox
	}

	/**
	 * Cleans the model <i>interfacesModel</i> and combobox <i>cbmInterfaces</i>
	 */
	public void cleanInterfaces(){
		cmbInterfaces.removeAllItems();			// Deletes all items from the model
		interfacesModel.removeAllElements();	// Deletes all items from the combobox
	}
	
	/**
	 * Reset the maximal of the loading bars
	 */
	public void resetBars(){
		upBar.resetMax();
		downBar.resetMax();
	}
}
